﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data;

using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using DomainDriver.DomainModeling.DomainObjects;
using DomainDriver.DomainModeling.StorageManagers.DataSetStorage;
using DomainDriver.DomainModeling.StorageManagers.EntityFrameworkStorage;
using ObjectRow = AutomotivePricingModel.AutomotivePricingDataSet.YearlyFinancialAssessmentsRow;
using NestedObjectRow = AutomotivePricingModel.AutomotivePricingDataSet.YearValueObservationsRow;

namespace AutomotivePricingModel.YearlyFinancialAssessments
{
    public partial class YearlyFinancialAssessment : IDataSetSerializable<AutomotivePricingDataSet, DataRow>
    {
        #region ADO .NET Entities Framework Storage

        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public Guid EF_YearlyFinancialAssessmentId
        {
            get { return m_Key; }
            set { m_Key = value; }
        }

        [Required]
        public int EF_MissingValueOption
        {
            get { return (int)m_MissingValueOption; }
            set { m_MissingValueOption = (MissingValueOption)value; }
        }

        //[Required]
        [NotMapped]
        public ICollection<YearValueObservation> EF_YearlyObservations
        {
            get
            {
                List<YearValueObservation> observations = new List<YearValueObservation>(m_YearlyObservations.Values);
                return observations;
            }
            set
            {
                m_YearlyObservations.Clear();
                foreach (YearValueObservation observation in value)
                {
                    m_YearlyObservations.Add(observation.Year, observation);
                }
            }
        }

        internal static YearlyFinancialAssessment ReadValueObject(AutomotivePricingDatabaseContext context, Guid assessmentId)
        {
            IQueryable<YearlyFinancialAssessment> assessmentResults = context.YearlyFinancialAssessments.Where<YearlyFinancialAssessment>((YearlyFinancialAssessment financialAssessment) => financialAssessment.EF_YearlyFinancialAssessmentId == assessmentId);
            if (assessmentResults.Count<YearlyFinancialAssessment>() < 0)
            { return null; }
            YearlyFinancialAssessment assessment = assessmentResults.First<YearlyFinancialAssessment>();

            IQueryable<YearValueObservation> observationResults = context.YearValueObservations.Where<YearValueObservation>((YearValueObservation observation) => observation.ParentYearlyFinancialAssessmentId == assessmentId);
            List<YearValueObservation> observationList = new List<YearValueObservation>(observationResults);
            assessment.EF_YearlyObservations = observationList;
            return assessment;
        }

        internal static void AddValueObject(AutomotivePricingDatabaseContext context, YearlyFinancialAssessment assessment)
        {
            context.YearlyFinancialAssessments.Add(assessment);

            Expression<Func<ICollection<YearValueObservation>>> nestedObjectsGetterExpression = () => assessment.EF_YearlyObservations;
            EfAggregateUtilities.AddNestedValues<YearValueObservation>(context, nestedObjectsGetterExpression);
        }

        internal static void UpdateValueObject(AutomotivePricingDatabaseContext context, YearlyFinancialAssessment updatedAssessment, YearlyFinancialAssessment originalAssessment)
        {
            Expression<Func<YearValueObservation, int>> keyGetterExpression = (YearValueObservation nestedObj) => nestedObj.Year;
            Expression<Func<YearValueObservation, YearValueObservation, bool>> nestedObjectsMatchExpression = (YearValueObservation obj1, YearValueObservation obj2) => ((obj1.ParentYearlyFinancialAssessmentId == obj2.ParentYearlyFinancialAssessmentId) && (obj1.Year == obj2.Year));
            Expression<Func<YearlyFinancialAssessment, IDictionary<int, YearValueObservation>>> dictionaryGetterExpression = (YearlyFinancialAssessment agg) => agg.m_YearlyObservations;
            EfAggregateUtilities.UpdateNestedValues<YearlyFinancialAssessment, int, YearValueObservation>(context, updatedAssessment, originalAssessment, keyGetterExpression, nestedObjectsMatchExpression, dictionaryGetterExpression);
        }

        internal static void DeleteValueObject(AutomotivePricingDatabaseContext context, YearlyFinancialAssessment assessment)
        {
            Expression<Func<YearValueObservation, bool>> yvoDeleteQueryExpression = ((YearValueObservation yvo) => (yvo.ParentYearlyFinancialAssessmentId == assessment.Key));
            EfAggregateUtilities.DeleteNestedValues(context, yvoDeleteQueryExpression);

            Expression<Func<YearlyFinancialAssessment, bool>> yfaDeleteQueryExpression = ((YearlyFinancialAssessment yfa) => (yfa.EF_YearlyFinancialAssessmentId == assessment.Key));
            EfAggregateUtilities.DeleteNestedValues(context, yfaDeleteQueryExpression);
        }

        #endregion

        #region AutomotivePricingDataSet Serialization

        public string ObjectTableName
        {
            get { return AutomotivePricingDataSet.SchemaHelper.YearlyFinancialAssessments.TableName; }
        }

        public string KeyColumnName
        {
            get { return AutomotivePricingDataSet.SchemaHelper.YearlyFinancialAssessments.EF_YearlyFinancialAssessmentIdColumn.ColumnName; }
        }

        public void Serialize(AutomotivePricingDataSet datasource, DataRow dataRow)
        {
            ObjectRow objectRecord = dataRow as ObjectRow;

            objectRecord.EF_YearlyFinancialAssessmentId = m_Key;
            objectRecord.EF_MissingValueOption = (int)m_MissingValueOption;

            datasource.YearlyFinancialAssessments.AddYearlyFinancialAssessmentsRow(objectRecord);

            foreach (YearValueObservation observation in m_YearlyObservations.Values)
            {
                NestedObjectRow nestedObjectRow = datasource.YearValueObservations.NewYearValueObservationsRow();
                observation.Serialize(datasource, nestedObjectRow);
            }
        }

        public void Deserialize(AutomotivePricingDataSet datasource, DataRow dataRow)
        {
            ObjectRow objectRecord = dataRow as ObjectRow;

            m_Key = objectRecord.EF_YearlyFinancialAssessmentId;
            m_MissingValueOption = (MissingValueOption)objectRecord.EF_MissingValueOption;

            m_YearlyObservations.Clear();
            foreach (NestedObjectRow nestedObjectRow in objectRecord.GetYearValueObservationsRows())
            {
                YearValueObservation observation = new YearValueObservation();
                observation.Deserialize(datasource, nestedObjectRow);
                m_YearlyObservations.Add(observation.Year, observation);
            }
        }

        #endregion
    }
}